import { _decorator, Component, Node, EventTarget } from 'cc';
const { ccclass, property } = _decorator;

// Define game event types
export enum GameEventType {
    ENEMY_SPAWN = 'enemy-spawn',
    ENEMY_DEATH = 'enemy-death',
    PLAYER_DAMAGE = 'player-damage',
    PLAYER_DEATH = 'player-death',
    ITEM_PICKUP = 'item-pickup',
    WEAPON_CHANGE = 'weapon-change',
    WEAPON_UPGRADE = 'weapon-upgrade',
    LEVEL_UP = 'level-up',
    GAME_START = 'game-start',
    GAME_OVER = 'game-over',
    GAME_PAUSE = 'game-pause',
    GAME_RESUME = 'game-resume',
    WAVE_START = 'wave-start',
    WAVE_END = 'wave-end',
    EXP_GAIN = 'exp-gain',
    SCORE_CHANGE = 'score-change'
}

@ccclass('EventManager')
export class EventManager extends Component {
    private static _instance: EventManager = null;
    private _eventTarget: EventTarget = new EventTarget();

    // Singleton pattern
    public static get instance(): EventManager {
        return this._instance;
    }

    onLoad() {
        // Establish singleton
        if (EventManager._instance === null) {
            EventManager._instance = this;
            this.node.parent.addChild(this.node);
        } else {
            this.node.destroy();
            return;
        }
    }

    /**
     * Register an event listener
     * @param eventType Event type from GameEventType enum
     * @param callback Callback function when event is triggered
     * @param target Target context for the callback
     */
    public on(eventType: GameEventType | string, callback: (...args: any[]) => void, target?: any): void {
        this._eventTarget.on(eventType, callback, target);
    }

    /**
     * Register a one-time event listener
     * @param eventType Event type from GameEventType enum
     * @param callback Callback function when event is triggered
     * @param target Target context for the callback
     */
    public once(eventType: GameEventType | string, callback: (...args: any[]) => void, target?: any): void {
        this._eventTarget.once(eventType, callback, target);
    }

    /**
     * Remove an event listener
     * @param eventType Event type from GameEventType enum
     * @param callback Callback function to remove
     * @param target Target context for the callback
     */
    public off(eventType: GameEventType | string, callback?: (...args: any[]) => void, target?: any): void {
        this._eventTarget.off(eventType, callback, target);
    }

    /**
     * Emit an event
     * @param eventType Event type from GameEventType enum
     * @param args Arguments to pass to the event listeners
     */
    public emit(eventType: GameEventType | string, ...args: any[]): void {
        this._eventTarget.emit(eventType, ...args);
    }
} 